home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DBio / DMegaSequence.cpp < prev    next >
Text File  |  1996-07-05  |  29KB  |  1,237 lines

  1. // DSequence.cp 
  2. // d.g.gilbert
  3.  
  4.  
  5.  
  6. #include "DMegaSequence.h"
  7. #include "DSeqFile.h"
  8. #include "DREnzyme.h"
  9. #include <ncbi.h>
  10. #include <dgg.h>
  11. #include <DUtil.h>
  12. #include <DFile.h>
  13. #include "ureadseq.h"
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24. // DMegaSequence -----------------
  25.  
  26.  
  27. DMegaSequence::DMegaSequence()
  28. {
  29.     fIsMega        = TRUE;
  30. }
  31.  
  32.  
  33. DMegaSequence::~DMegaSequence()  
  34. {
  35. }
  36.  
  37.  
  38. DObject* DMegaSequence::Clone() // override 
  39. {    
  40.     DMegaSequence* aSeq= (DMegaSequence*) DSequence::Clone();
  41. #if 0
  42.     aSeq->fBases= NULL; aSeq->SetBases( fBases, true);  
  43.     aSeq->fMasks= NULL; aSeq->SetMasks( fMasks, true); 
  44.     aSeq->fInfo=  StrDup( fInfo);
  45.     aSeq->fName=  StrDup( fName);
  46.     aSeq->fSearchRec.targ= StrDup( fSearchRec.targ);
  47. #endif
  48.     return aSeq;
  49. }
  50.  
  51. void DMegaSequence::CopyContents( DSequence* fromSeq)
  52. {
  53.     DSequence::CopyContents( fromSeq);
  54. }
  55.  
  56.  
  57. char* DMegaSequence::Bases() const {
  58.     return fBases; // fix later
  59.     }
  60.  
  61. char* DMegaSequence::Masks() const {
  62.     return fMasks; // fix later
  63.     }
  64.     
  65.     
  66. enum { kHugePartSize = 3000000 }; // = kMegaPartSize 
  67.  
  68. void DMegaSequence::countparts( char* seq, long& len, long& nparts, long& partsize)
  69. {
  70.     char* cp= seq;
  71.     partsize= kHugePartSize;  
  72.     len= 0;
  73.     nparts= 0;
  74.     if (!seq) return;
  75.     
  76.     while ( *cp != '\0' ) {
  77.         long  n;
  78.         for (n=0; *cp && n<kHugePartSize; n++) cp++;
  79.         len += n;
  80.         nparts++;    
  81.         }    
  82.     if (nparts == 1) partsize= len;
  83. }
  84.  
  85.  
  86. void DMegaSequence::SetBases( char*& theBases, Boolean duplicate)
  87. {
  88.     long  newlen= (theBases) ? StrLen(theBases) : 0;
  89.     if (fBases) { 
  90.         if (fLength>0 && 
  91.             (fLength != newlen || MemCmp( theBases, fBases, newlen)!= 0))
  92.                 fChanged= TRUE;
  93.         MemFree(fBases); 
  94.         fBases= NULL; fLength= 0; 
  95.         }
  96.  
  97.     if (theBases) {
  98.         countparts( theBases, fLength, fNparts, fPartsize);
  99.         
  100.         if (fNparts==1) {
  101.             if (duplicate) fBases = StrDup(theBases);  
  102.             else { fBases= theBases; theBases= NULL; }
  103.             }
  104.             
  105.         else if (fNparts>1) {
  106.                 // temp for testing !
  107.             fLength= fPartsize;
  108.             fBases= (char*)MemNew( fLength+1);
  109.             MemCpy( fBases, theBases, fLength);
  110.             fBases[fLength]= 0;
  111.             }
  112.         
  113.         }
  114.     fModTime= gUtil->time();
  115.     fMasksOk= false; // assume SetBases allways called before SetMask...
  116. }
  117.  
  118.  
  119. void DMegaSequence::UpdateBases( char* theBases, long theLength)
  120. {
  121.     fBases =  theBases;  
  122.     fLength= theLength;
  123.     fMasksOk= false; // assume this allways called before SetMask...
  124. }
  125.  
  126.  
  127. void DMegaSequence::SetMasks( char*& theMasks, Boolean duplicate)
  128. {
  129.     if (fMasks) MemFree(fMasks);
  130.     if (theMasks) {
  131.         if (duplicate) fMasks = StrDup(theMasks);  
  132.         else { fMasks= theMasks; theMasks= NULL; }
  133.         FixMasks();
  134.         }
  135.     else {
  136.         fMasks= NULL;
  137.         fMasksOk= false;
  138.         }
  139. }
  140.  
  141. void DMegaSequence::FixMasks()
  142. {
  143.     ulong i, mlen= 0;
  144.     if (!fMasks) { 
  145.         mlen= 1+fLength;
  146.         fMasks= (char*) MemGet(mlen,true);  
  147.         for (i=0; i<mlen; i++) fMasks[i] |= 0x80; // set high bit so Strxxx sees it as non-null
  148.         fMasks[mlen-1]= 0;
  149.         }
  150.     else { 
  151.         mlen= 1+StrLen(fMasks);
  152.         if (fLength+1 != mlen) {
  153.             fMasks= (char*) Nlm_MemExtend( fMasks, fLength+1, mlen);
  154.             mlen= fLength+1; 
  155.             for (i=0; i<mlen; i++) fMasks[i] |= 0x80; 
  156.             fMasks[mlen-1]= 0;
  157.             } 
  158.         }
  159.     fMasksOk= true;
  160. }
  161.  
  162. short DMegaSequence::MaskAt(long baseindex, short masklevel)
  163. {
  164.     short b = kMaskEmpty;
  165.     if (fMasks && fMasksOk && baseindex>=0 && baseindex<fLength) {
  166.         b= (unsigned char) fMasks[baseindex];
  167.         switch (masklevel) {
  168.             case 0: b &= 0x7f; break; // return full mask - top (0x80) bit
  169.             case 1: b &= 1;  break;  
  170.             case 2: b &= 2;  break;
  171.             case 3: b &= 4;  break;
  172.             case 4: b &= 8;  break;
  173.             default: b = kMaskEmpty; break;
  174.             }
  175.         }
  176.     return b;
  177. }
  178.  
  179. Boolean DMegaSequence::IsMasked(unsigned char maskbyte, short masklevel)
  180. {
  181.     short b= (unsigned char) maskbyte;
  182.     switch (masklevel) {
  183.         case 0: b &= 0x7f; break; // return full mask - top (0x80) bit
  184.         case 1: b &= 1;  break;  
  185.         case 2: b &= 2;  break;
  186.         case 3: b &= 4;  break;
  187.         case 4: b &= 8;  break;
  188.         default: b = kMaskEmpty; break;
  189.         }
  190.     return (b > 0);
  191. }
  192.  
  193.  
  194. inline void SetMaskByte( char& b, short masklevel, short maskval)
  195. {
  196.     switch (masklevel) {
  197.         case 1: if (maskval) b |= 1; else b &= ~1; break;
  198.         case 2: if (maskval) b |= 2; else b &= ~2; break;
  199.         case 3: if (maskval) b |= 4; else b &= ~4; break;
  200.         case 4: if (maskval) b |= 8; else b &= ~8; break;
  201.         // reserve bits 5, 6, 7 & 8 for now 
  202.         // -- 7 & 8 may go unused to store data in printchar form
  203.         default: break;
  204.         }
  205.     //if (b) masklevel--; // debugging b val
  206. }
  207.  
  208. void DMegaSequence::SetMaskAt(long baseindex, short masklevel, short maskval)
  209. {
  210.     if (fMasks && fMasksOk && baseindex>=0 && baseindex<fLength)  
  211.         ::SetMaskByte(fMasks[baseindex],masklevel, maskval);
  212. }
  213.  
  214.  
  215. void DMegaSequence::SetMask(short masklevel, short maskval)
  216. {
  217.     long  baseindex;
  218.     if (fMasks && fMasksOk) 
  219.      for (baseindex=0; baseindex<fLength; baseindex++) 
  220.         ::SetMaskByte(fMasks[baseindex], masklevel, maskval);
  221. }
  222.  
  223.  
  224. inline void FlipMaskByte( char& b, short masklevel)
  225. {
  226.     switch (masklevel) {
  227.         case 1: b ^= 1;  break;  
  228.         case 2: b ^= 2;  break;
  229.         case 3: b ^= 4;  break;
  230.         case 4: b ^= 8;  break;
  231.         default:  break;
  232.         }
  233.     //if (b) masklevel--; // debugging b val
  234. }
  235.  
  236. void DMegaSequence::FlipMaskAt(long baseindex, short masklevel)
  237. {
  238.     if (fMasks && fMasksOk && baseindex>=0 && baseindex<fLength)  
  239.         ::FlipMaskByte(fMasks[baseindex],masklevel);
  240. }
  241.  
  242. void DMegaSequence::FlipMask(short masklevel)
  243. {
  244.     long  baseindex;
  245.     if (fMasks && fMasksOk) 
  246.      for (baseindex=0; baseindex<fLength; baseindex++)  
  247.         FlipMaskByte(fMasks[baseindex],masklevel);
  248. }
  249.  
  250.  
  251.  
  252. void DMegaSequence::UpdateFlds()
  253. {
  254.     long         seqlen;
  255.     short     kind;
  256.     unsigned long check;
  257.     fLength= StrLen(fBases);
  258.     GetSeqStats(fBases, fLength, &kind, &check, &seqlen);
  259.     //fValidLength= seqlen; //?? is fLength == StrLen(fBases) or is it <= that, only valid bases??
  260.     fKind            = kind;
  261.     fChecksum    = check;
  262.     fChanged    = FALSE;
  263. }
  264.  
  265.  
  266.  
  267.  
  268.  
  269. void DMegaSequence::SetSelection( long start, long nbases)
  270. {
  271.     fSelStart= start;
  272.     fSelBases= nbases;
  273. }
  274.  
  275. void DMegaSequence::ClearSelection()
  276. {
  277.     fSelStart= 0;
  278.     fSelBases= 0;
  279. }
  280.  
  281. void    DMegaSequence::GetSelection( long& start, long& nbases)
  282. {
  283.     if (fSelBases==0) {
  284.         start= 0;
  285.         nbases= fLength;
  286.         }    
  287.     else if (fLength>0) {
  288.         start= fSelStart;
  289.         nbases= Min( fSelBases, fLength - fSelStart);
  290.         }    
  291.     else {
  292.         start= 0;
  293.         nbases= 0;
  294.         }
  295. }
  296.  
  297.  
  298. DSequence* DMegaSequence::CopyRange()
  299. {  
  300.             //note: start == 0 == 1st position 
  301.     DMegaSequence* aSeq= (DMegaSequence*) Clone();
  302.     if (fSelStart > 0 || fSelBases > 0) {
  303.         char* h= aSeq->fBases;
  304.         char* m= aSeq->fMasks;
  305.         Boolean domask= (fMasks && fMasksOk);
  306.  
  307.         long len= aSeq->fLength;
  308.         if (fSelStart > 0) {
  309.             len -= fSelStart;
  310.             MemMove( h, h + fSelStart, len);
  311.             if (domask) MemMove( m, m + fSelStart, len);
  312.             }
  313.         if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  314.         h= (char*) MemMore( h, len+1);
  315.         h[len]= '\0'; //((char*)h+len) = '\0';
  316.         aSeq->fBases= h;
  317.         if (domask) {
  318.             m= (char*) MemMore( m, len+1);
  319.             m[len]= '\0';    
  320.             aSeq->fMasks= m;
  321.             }
  322.         }
  323.     aSeq->UpdateFlds();
  324.     aSeq->Modified();
  325.     return aSeq;
  326. }
  327.  
  328.  
  329. DSequence* DMegaSequence::CutRange()
  330. {
  331. /* aSeq.Cutrange means:  
  332.         (a) selected range (fSelStart..fSelStart+fSelBases) is copied into Result; &&
  333.         (b) selected range is removed from this
  334. */
  335.  
  336.     DMegaSequence* aSeq= (DMegaSequence*) CopyRange();
  337.     if (fSelStart > 0 || fSelBases > 0) {
  338.         if (fSelStart<0) fSelStart= 0;
  339.         char* h= this->fBases;
  340.         char* m= this->fMasks;
  341.         Boolean domask= (fMasks && fMasksOk);
  342.         long len= this->fLength;
  343.         long top= len - fSelStart - fSelBases;
  344.         if (fSelBases > 0 && fSelBases < len) {
  345.             MemMove( h+fSelStart, h+fSelStart+fSelBases, top);
  346.             if (domask) MemMove( m+fSelStart, m+fSelStart+fSelBases, top);
  347.             }
  348.         len= fSelStart + top;
  349.         h= (char*) MemMore( h, len+1);
  350.         *((char*)h+len)= '\0';       //h[len]= '\0';
  351.         this->fBases= h;
  352.         if (domask) {
  353.             m= (char*) MemMore( m, len+1);
  354.             *((char*)m+len)= '\0';    
  355.             this->fMasks= m;
  356.             }
  357.         }
  358.     UpdateFlds();    
  359.     Modified();
  360.     return aSeq;
  361. }
  362.  
  363. void DMegaSequence::InsertSpacers( long insertPoint, long insertCount, char spacer)
  364.     long i;
  365.     char *cp;
  366.     char* h= this->fBases;
  367.     char* m= this->fMasks;
  368.     Boolean domask= (fMasks && fMasksOk);
  369.     long len= this->fLength;
  370.     if (insertPoint<0) insertPoint= 0;
  371.     else if (insertPoint>len-1) insertPoint= len-1;
  372.     h= (char*) MemMore( h, len+insertCount+1);
  373.     cp = h+insertPoint;
  374.     MemMove( cp+insertCount, cp, len-insertPoint);
  375.     for ( i= 0; i<insertCount; i++)  *cp++= spacer;
  376.     h[len+insertCount]= '\0';
  377.     this->fBases= h;
  378.     if (domask) {
  379.         m= (char*) MemMore( m, len+insertCount+1);
  380.         cp = m+insertPoint;
  381.         char cmask= *cp;
  382.         MemMove( cp+insertCount, cp, len-insertPoint);
  383.         for ( i= 0; i<insertCount; i++)  *cp++= cmask;
  384.         m[len+insertCount]= '\0';
  385.         this->fMasks= m;
  386.         }
  387.     this->UpdateFlds();    
  388.     this->Modified();
  389. }
  390.  
  391.  
  392. DSequence* DMegaSequence::PasteBases( long insertPoint, char* fromBases, char* fromMasks)
  393.     long add;
  394.     DMegaSequence* aSeq= (DMegaSequence*) Clone();
  395.     if (fromBases) add= StrLen( fromBases);  else add= 0;
  396.     if (add>0) {
  397.         char* h= aSeq->fBases;
  398.         char* m= aSeq->fMasks;
  399.         Boolean domask= (fMasks && fMasksOk);
  400.         long len = aSeq->fLength;
  401.         if (insertPoint<=0) {
  402.             fromBases= StrDup( fromBases);
  403.             StrExtendCat( &fromBases, h);
  404.             MemFree( h);
  405.             h= fromBases;
  406.             if (domask && fromMasks) {
  407.                 fromMasks= StrDup( fromMasks);
  408.                 StrExtendCat( &fromMasks, m);
  409.                 MemFree( m);
  410.                 m= fromMasks;
  411.                 }
  412.             }        
  413.         else if (insertPoint>=len) { 
  414.             StrExtendCat( &h, fromBases);
  415.             if (domask) StrExtendCat( &m, fromMasks);
  416.             }
  417.         else { 
  418.             h= (char*) MemMore( h, len+add);
  419.             MemMove( h+insertPoint+add, h+insertPoint, len-insertPoint);
  420.             MemMove( h+insertPoint+add, fromBases, add);
  421.             *((char*)h+len+add)= '\0';
  422.             if (domask) {
  423.                 m= (char*) MemMore( m, len+add);
  424.                 MemMove( m+insertPoint+add, m+insertPoint, len-insertPoint);
  425.                 MemMove( m+insertPoint+add, fromMasks, add);
  426.                 *((char*)m+len+add)= '\0';
  427.                 }
  428.             }
  429.         aSeq->fBases= h;
  430.         aSeq->fMasks= m;
  431.         }
  432.     aSeq->UpdateFlds();    
  433.     aSeq->Modified();
  434.     return aSeq;
  435. }
  436.  
  437.  
  438. DSequence* DMegaSequence::Reverse()
  439. {
  440.     long i;
  441.     DMegaSequence* aSeq= (DMegaSequence*) Clone();    
  442.     if (fSelStart < 0) fSelStart= 0;
  443.     long len= aSeq->fLength - fSelStart;
  444.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  445.     char* pc= this->fBases+fSelStart + len;
  446.     char* pr= aSeq->fBases+fSelStart;
  447.     for (i= 0; i<len; i++) *pr++= *--pc;
  448.     Boolean domask= (fMasks && fMasksOk);
  449.     if (domask) {
  450.         pc= this->fMasks+fSelStart + len;
  451.         pr= aSeq->fMasks+fSelStart;
  452.         for (i= 0; i<len; i++) *pr++= *--pc;
  453.         }
  454.     aSeq->UpdateFlds();
  455.     aSeq->Modified();
  456.     return aSeq;
  457. }
  458.  
  459.  
  460. DSequence* DMegaSequence::Complement()
  461. // A->T, T->A, G->C, C->G  
  462. {
  463.     Boolean        isrna;
  464.     DMegaSequence* aSeq= (DMegaSequence*) Clone();    
  465.     
  466.     if (fKind == kRNA) isrna= TRUE;
  467.     else if (fKind == kDNA || fKind == kNucleic) isrna= FALSE;
  468.     else return aSeq;    
  469.         
  470.     if (fSelStart < 0) fSelStart= 0;
  471.     long len= aSeq->fLength - fSelStart;
  472.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  473.     char* pc= this->fBases+fSelStart;
  474.     char* pr= aSeq->fBases+fSelStart;
  475.     NucleicComplement( isrna, pc, pr, len);
  476.         
  477.     aSeq->UpdateFlds();
  478.     aSeq->Modified();
  479.     return aSeq;
  480. }
  481.  
  482.  
  483.  
  484. DSequence* DMegaSequence::ChangeCase(Boolean toUpper)
  485. // g->G or G->g
  486. {
  487.     DMegaSequence* aSeq= (DMegaSequence*) Clone();    
  488.     
  489.     if (fSelStart < 0) fSelStart= 0;
  490.     char* h= aSeq->fBases;
  491.     long len= aSeq->fLength - fSelStart;
  492.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  493.     char* pc= this->fBases+fSelStart;
  494.     char* pr= aSeq->fBases+fSelStart;
  495.     
  496.     long i;
  497.     if (toUpper) for (i= 0; i<len; i++) {
  498.         *pr++= toupper(*pc); pc++;
  499.         }
  500.     else for (i= 0; i<len; i++) {
  501.         *pr++= tolower(*pc); pc++;
  502.         }    
  503.         
  504.     aSeq->UpdateFlds();
  505.     aSeq->Modified();
  506.     return aSeq;
  507. }
  508.  
  509. DSequence* DMegaSequence::Dna2Rna(Boolean toRna)
  510. // T->U or U->T 
  511. {
  512.     Boolean        isrna;
  513.     DMegaSequence* aSeq= (DMegaSequence*) Clone();    
  514.     
  515.     if (fKind==kRNA) isrna= TRUE;
  516.     else if (fKind == kDNA || fKind == kNucleic) isrna= FALSE;
  517.     else return aSeq;    
  518.      
  519.     if (fSelStart < 0) fSelStart= 0;
  520.     long len= aSeq->fLength - fSelStart;
  521.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  522.     char* pc= this->fBases+fSelStart;
  523.     char* pr= aSeq->fBases+fSelStart;
  524.     
  525.     long i;
  526.     char b, c;
  527.     if (toRna) for (i= 0; i<len; i++) {
  528.         b= *pc++;
  529.         if (b=='T') c= 'U';
  530.         else if (b=='t') c= 'u';
  531.         else c= b;
  532.         *pr++= c;
  533.         }
  534.     else for (i= 0; i<len; i++) {
  535.         b= *pc++;
  536.         if (b=='U') c= 'T';
  537.         else if (b=='u') c= 't';
  538.         else c= b;
  539.         *pr++= c;
  540.         }    
  541.         
  542.     aSeq->UpdateFlds();
  543.     aSeq->Modified();
  544.     return aSeq;
  545. }
  546.  
  547.  
  548. DSequence* DMegaSequence::OnlyORF(char nonorf)
  549. // convert sequence to ORF part only 
  550. {
  551.     return DSequence::OnlyORF(nonorf);    
  552. }
  553.  
  554. DSequence* DMegaSequence::LockIndels( Boolean doLock)
  555. // indelSoft -> indelHard or vice versa 
  556. {    
  557.     char b, c, fromc, toc;
  558.     DMegaSequence* aSeq= (DMegaSequence*) Clone();    
  559.     
  560.     if (fSelStart < 0) fSelStart= 0;
  561.     long  len= aSeq->fLength - fSelStart;
  562.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  563.     char* pc= this->fBases+fSelStart;
  564.     char* pr= aSeq->fBases+fSelStart;
  565.     
  566.     if (doLock) { fromc= indelSoft; toc= indelHard; }
  567.     else { fromc= indelHard; toc= indelSoft; }
  568.     
  569.     for (long i= 0; i<len; i++) {
  570.         b= *pc++;
  571.         if (b == fromc) c= toc;
  572.         else c= b;
  573.         *pr++= c;
  574.         }    
  575.         
  576.     aSeq->UpdateFlds();
  577.     aSeq->Modified();
  578.     return aSeq;
  579. }
  580.  
  581.  
  582. DSequence* DMegaSequence::Slide( long slideDist)
  583. /* insert "-" below (+dist) or above (-dist) of seq range,
  584.     squeeze out "-" above (below) of range
  585. */
  586. {     
  587.     long         slideSave, newlen, fulllen, len, i, j= 0;
  588.     char         b, cutchar, cutmask;
  589.     char        *pc, *pr;
  590.     
  591.     DMegaSequence* aSeq= (DMegaSequence*) Clone();    
  592.     if (fSelStart < 0) fSelStart= 0;
  593.     fulllen= aSeq->fLength;
  594.     len= fulllen - fSelStart;
  595.     Boolean domask= (fMasks && fMasksOk);
  596.     Boolean dosqueeze= true; //(indelSoft & 0x80 != 0); // quick fix flag
  597.     indelSoft &= 0x7f;
  598.     
  599.     if (slideDist < 0) {
  600.         // tough... do if below works...
  601.         // really need ability to extend seq in 5' (lower) direction 
  602.         //! build pr in reverse, then flip it....
  603.  
  604.         if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  605.         slideDist= -slideDist;
  606.         slideSave= slideDist;
  607.         aSeq->fBases= (char*) MemMore(aSeq->fBases, 2+fulllen+slideDist);
  608.         pr= aSeq->fBases;
  609.         pc= this->fBases + fulllen;
  610.         for (i= fulllen-1; i >= fSelStart+len; i--) *pr++= *--pc;
  611.              
  612.         if (pr == aSeq->fBases || *(pr-1) == indelEdge) cutchar= indelEdge;
  613.         else cutchar= indelSoft; //??
  614.         for (i=0; i<slideDist; i++) *pr++= cutchar;
  615.  
  616.         pc= this->fBases+fSelStart+len;
  617.         for (i= fSelStart+len-1; i >= fSelStart; i--) *pr++= *--pc;
  618.             
  619.         pc= this->fBases+fSelStart;
  620.         for (i= fSelStart-1; i>=0; i--) {
  621.             b= *--pc;
  622.             if (dosqueeze && slideDist>0 && (b==indelSoft || b==indelEdge)) slideDist--;
  623.             else {
  624.                 *pr++= b;
  625.                 }
  626.             }
  627.  
  628.         newlen= pr - aSeq->fBases;
  629.         char* htmp= (char*) MemNew(newlen+1);
  630.         pc= htmp;
  631.         for (i=0; i<newlen; i++) *pc++= *--pr; //pr[j-i+1];
  632.         pc= '\0';
  633.         MemFree(aSeq->fBases);
  634.         aSeq->fBases = htmp;  
  635.         aSeq->fLength= newlen;
  636.         aSeq->fOrigin= fulllen - newlen; //== this->fLength - aSeq->fLength
  637.  
  638.         if (domask) {
  639.             slideDist= slideSave;
  640.             aSeq->fMasks= (char*) MemMore(aSeq->fMasks, 2+fulllen+slideDist);
  641.             pr= aSeq->fMasks;
  642.             pc= this->fMasks + fulllen;
  643.             for (i= fulllen-1; i >= fSelStart+len; i--) *pr++= *--pc;
  644.                  
  645.             cutmask= 0x80; // required empty mask  
  646.             for (i=0; i<slideDist; i++) *pr++= cutmask;
  647.     
  648.             pc= this->fMasks+fSelStart+len;
  649. #ifdef WIN_MSWIN
  650.             // mswin is crashing here for no obvious reason
  651.             //pc--; len--;
  652.             for (i= fSelStart + len - 1; i >= fSelStart; i--) {
  653.                  register short amask;
  654.                  --pc;
  655.                  amask= *pc;    //mswin bomb is here !
  656.                  *pr= amask;
  657.                  pr++;
  658.          }
  659. #else
  660.             for (i= fSelStart+len-1; i >= fSelStart; i--) *pr++= *--pc;
  661. #endif
  662.             pc= this->fMasks+fSelStart;
  663.             for (i= fSelStart-1; i>=0; i--) {
  664.                 b= *--pc;
  665.                 if (slideDist>0 && (b==cutmask)) slideDist--;
  666.                 else {
  667.                     *pr++= b;
  668.                     }
  669.                 }
  670.                 
  671.             newlen= pr - aSeq->fMasks;
  672.             htmp= (char*) MemNew(newlen+1);
  673.             pc= htmp;
  674.             for (i=0; i<newlen; i++) *pc++= *--pr; //pr[j-i+1];
  675.             pc= '\0';
  676.             MemFree(aSeq->fMasks);
  677.             aSeq->fMasks = htmp;  
  678.             }
  679.             
  680.         }    
  681.         
  682.     else if (slideDist > 0) {
  683.         fulllen= len;
  684.         if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  685.         aSeq->fBases= (char*) MemMore(aSeq->fBases, 2+fSelStart+fulllen+slideDist); //make it large enough
  686.  
  687.         pr= aSeq->fBases;
  688.       if (fSelStart==0 || pr[fSelStart-1]==indelEdge) cutchar= indelEdge; 
  689.         else cutchar= indelSoft; 
  690.  
  691.         pc= this->fBases+fSelStart;
  692.         pr= aSeq->fBases+fSelStart;
  693.  
  694.         for (j= 0; j<slideDist; j++) *pr++= cutchar;
  695.         for (i= 0; i<len; i++) *pr++= *pc++; 
  696.     
  697.         for (i= len; i<fulllen; i++) {
  698.             b= *pc++;
  699.             if (dosqueeze && slideDist>0 && (b==indelSoft || b==indelEdge)) 
  700.                 slideDist--;
  701.             else {
  702.                 *pr++= b;
  703.                 }
  704.             }
  705.         
  706.         *pr= 0;
  707.         newlen= pr - aSeq->fBases; 
  708.         aSeq->fBases= (char*)MemMore(aSeq->fBases, newlen+1);  
  709.         
  710.         if (domask) {
  711.             aSeq->fMasks= (char*) MemMore(aSeq->fMasks, 2+fSelStart+fulllen+slideDist);
  712.           cutmask= 0x80; 
  713.             pc= this->fMasks+fSelStart;
  714.             pr= aSeq->fMasks+fSelStart;
  715.     
  716.             for (j= 0; j<slideDist; j++) *pr++= cutmask;
  717.             for (i= 0; i<len; i++) *pr++= *pc++; 
  718.  
  719.             for (i= len; i<fulllen; i++) {
  720.                 b= *pc++;
  721.                 if (slideDist>0 && (b==cutmask)) // this is BAD? must be done w/ base slide !?
  722.                     slideDist--;
  723.                 else {
  724.                     *pr++= b;
  725.                     }
  726.                 }
  727.             
  728.             *pr= 0;
  729.             newlen= pr - aSeq->fMasks; 
  730.             aSeq->fMasks= (char*)MemMore(aSeq->fMasks, newlen+1);  
  731.             }
  732.         }
  733.             
  734.     aSeq->UpdateFlds();
  735.     aSeq->Modified();
  736.     return aSeq;
  737. }
  738.  
  739.  
  740. DSequence* DMegaSequence::Compress()
  741. // pull out "-", ".", ? anything but nuc/aa codes ? 
  742. {
  743.     long  len, fulllen, i;
  744.     char     b, c;
  745.     char * mc, * mr;
  746.     Boolean domask= (fMasks && fMasksOk);
  747.  
  748.     DMegaSequence* aSeq= (DMegaSequence*) Clone();    
  749.     if (fSelStart < 0) fSelStart= 0;
  750.     len= aSeq->fLength - fSelStart;
  751.     fulllen= len;
  752.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  753.     char* pc= this->fBases+fSelStart;
  754.     char* pr= aSeq->fBases+fSelStart;
  755.     if (domask) {
  756.         mc= this->fMasks+fSelStart;
  757.         mr= aSeq->fMasks+fSelStart;
  758.         }
  759.         
  760.     if (domask) for (i= 0; i<len; i++) {
  761.         b= *pc++;
  762.         c= *mc++;
  763.         if (b!=indelSoft && b!=indelEdge) { 
  764.             *pr++= b;
  765.             *mr++= c;
  766.             }
  767.         }
  768.     else for (i= 0; i<len; i++) {
  769.         b= *pc++;
  770.         if (b!=indelSoft && b!=indelEdge) 
  771.             *pr++= b;
  772.         }
  773.     for (i=len; i<fulllen; i++) *pr++= *pc++;
  774.     if (domask) for (i=len; i<fulllen; i++) *mr++= *mc++;
  775.  
  776.     long newlen= pr - aSeq->fBases;
  777.     aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen+1);
  778.     aSeq->fBases[newlen]= 0;
  779.     if (domask) {
  780.         aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen+1);
  781.         aSeq->fMasks[newlen]= 0;
  782.         }
  783.         
  784.     aSeq->UpdateFlds();
  785.     aSeq->Modified();
  786.     return aSeq;
  787. }
  788.  
  789.  
  790.  
  791.  
  792. DSequence* DMegaSequence::CompressFromMask(short masklevel)
  793. {
  794.     long  len, fulllen, i;
  795.     char     b, c;
  796.     char * mc, * mr;
  797.     Boolean domask= (fMasks && fMasksOk && masklevel>0);
  798.  
  799.     if (!domask) return NULL; // or aSeq ???
  800.     DMegaSequence* aSeq= (DMegaSequence*) Clone();    
  801.     //if (!domask) return aSeq;  
  802.  
  803.     if (fSelStart < 0) fSelStart= 0;
  804.     len= aSeq->fLength - fSelStart;
  805.     fulllen= len;
  806.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  807.     char* pc= this->fBases+fSelStart;
  808.     char* pr= aSeq->fBases+fSelStart;
  809.     mc= this->fMasks+fSelStart;
  810.     mr= aSeq->fMasks+fSelStart;
  811.          
  812.     for (i= 0; i<len; i++) {
  813.         b= *pc++;
  814.         c= *mc++;
  815.         if (IsMasked(c, masklevel)) { 
  816.             *pr++= b;
  817.             *mr++= c;
  818.             }
  819.         }
  820.     for (i=len; i<fulllen; i++) *pr++= *pc++;
  821.     for (i=len; i<fulllen; i++) *mr++= *mc++;
  822.  
  823.     long newlen= pr - aSeq->fBases;
  824.     aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen+1);
  825.     aSeq->fBases[newlen]= 0;
  826.     aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen+1);
  827.     aSeq->fMasks[newlen]= 0;
  828.         
  829.     aSeq->UpdateFlds();
  830.     aSeq->Modified();
  831.     return aSeq;
  832. }
  833.  
  834.  
  835.  
  836. DSequence* DMegaSequence::Translate(Boolean keepUnselected)
  837. {    
  838.     char  c;
  839.     char    acodon[3];
  840.     Boolean isrna, nocodon;
  841.     char    *pr, *pc, *mr, *mc;
  842.     long    len, fulllen, newlen, i, j, k;
  843.     
  844.     DMegaSequence* aSeq= (DMegaSequence*) Clone();        
  845.     if (DCodons::NotAvailable()) return aSeq; // safer than returning NULL !?
  846.     // !? what do we do w/ fMasks !?
  847.     Boolean domask= (fMasks && fMasksOk);
  848.     
  849.     if (fSelStart < 0) fSelStart= 0;
  850.     fulllen= this->fLength - fSelStart;
  851.     len= fulllen;
  852.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  853.     
  854.     switch (fKind) {
  855.     
  856.         case kRNA:
  857.         case kDNA:
  858.         case kNucleic: 
  859.             {
  860.             if (keepUnselected) {
  861.                 pr= aSeq->fBases + fSelStart; // start at selection, leaving untranslated 5'
  862.                 if (domask) mr= aSeq->fMasks + fSelStart;
  863.                 }
  864.             else {
  865.                 pr= aSeq->fBases;
  866.                  if (domask) mr= mr= aSeq->fMasks;
  867.                  }
  868.                  
  869.             pc= this->fBases + fSelStart;
  870.             if (domask) mc= this->fMasks + fSelStart;
  871.             isrna= (fKind == kRNA);
  872.             i= fSelStart;
  873.             while (i < len) {
  874.                 for (j=0; j<3; j++) {
  875.                     c= toupper( *pc); pc++; // toupper is sometimes a MACRO ! no (*pc++) !
  876.                     if (isrna && c=='U') c= 'T';
  877.                     acodon[j]= c;
  878.                     }
  879.                 i += 3;
  880.                 for (k= 0, nocodon= true; k<64; k++) 
  881.                     if ( MemCmp(DCodons::codon(k),acodon,3) == 0) { 
  882.                         *pr++= DCodons::amino(k); //gCodonTable[k].amino;
  883.                         nocodon= false;
  884.                         break;
  885.                         }
  886.                 if (nocodon) *pr++= '?';
  887.                 if (domask) {
  888.                     *mr++= *mc;
  889.                     mc += 3;
  890.                     }
  891.                 }
  892.                  // copy over untranslated portion
  893.             if (keepUnselected) {
  894.                 long savei= i;
  895.                 for ( ; i < fulllen; i++)  *pr++= *pc++; 
  896.                 if (domask) for ( i= savei; i < fulllen; i++)  *mr++= *mc++; 
  897.                 }
  898.             }
  899.             break;
  900.             
  901.         case kAmino: 
  902.             {
  903.             char *bestcodon;
  904.             long  selend;
  905.             
  906.             if (len < fulllen) {
  907.                 newlen= fulllen + len*3;
  908.                 selend= fSelStart + len;
  909.                 }
  910.             else {
  911.                 newlen= fulllen * 3;
  912.                 selend= len;
  913.                 }
  914.             pc= this->fBases + fSelStart;
  915.             aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen);
  916.             if (keepUnselected)
  917.                 pr= aSeq->fBases + fSelStart;
  918.             else
  919.                 pr= aSeq->fBases;
  920.                 
  921.             if (domask) {
  922.                 mc= this->fMasks + fSelStart;
  923.                 aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen);
  924.                 if (keepUnselected)
  925.                     mr= aSeq->fMasks + fSelStart;
  926.                 else
  927.                     mr= aSeq->fMasks;
  928.                 }
  929.                 
  930.             for (i= fSelStart; i<selend; i++) {
  931.                 c= toupper( *pc); pc++;// toupper is sometimes a MACRO ! no (*pc++) !
  932.                 bestcodon= (char*) DCodons::FindBestCodon(c);
  933.                 MemCpy( pr, bestcodon, 3);  
  934.                 pr += 3;
  935.                 if (domask) {
  936.                     for (j=0; j<3; j++) *mr++= *mc;
  937.                     mc++;
  938.                     }
  939.                 }
  940.                  // copy over untranslated portion
  941.             if (keepUnselected) {
  942.                 long savei= i;
  943.                 for ( ; i < fulllen; i++)  *pr++= *pc++; 
  944.                 if (domask) for ( i=savei; i < fulllen; i++)  *mr++= *mc++; 
  945.                 }
  946.             }
  947.             break;
  948.         
  949.         default:
  950.             return NULL;
  951.          
  952.       }
  953.         
  954.     *pr= '\0';
  955.     newlen= pr - aSeq->fBases;
  956.     aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen);
  957.     if (domask) {
  958.         *mr= '\0';
  959.         newlen= mr - aSeq->fMasks;
  960.         aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen);
  961.         }
  962.     aSeq->UpdateFlds();
  963.     aSeq->Modified();
  964.     return aSeq;    
  965. }
  966.  
  967.  
  968.  
  969.  
  970. void DMegaSequence::DoWrite(DFile* aFile, short format)
  971. {  
  972.     if (fLength>0) {
  973.         DSeqFile::WriteSeqWrapper( aFile, fBases, fLength, format, fName);
  974.         if (fMasks && fMasksOk && DSeqFile::gWriteMasks) 
  975.             DSeqFile::WriteMaskWrapper( aFile, fMasks, fLength, format, fName);
  976.         }
  977. }
  978.  
  979.  
  980. void DMegaSequence::DoWriteSelection(DFile* aFile, short format)
  981. {
  982.     if (fSelBases==0) 
  983.         DoWrite( aFile, format);
  984.     else if (fLength>0) {
  985.         long aStart= Min( fSelStart, fLength);
  986.         long aLength= Min( fSelBases, fLength - fSelStart);
  987.         DSeqFile::WriteSeqWrapper(  aFile, fBases+aStart, aLength, format, fName);
  988.         if (fMasks && fMasksOk && DSeqFile::gWriteMasks)  
  989.             DSeqFile::WriteMaskWrapper( aFile, fMasks+aStart, aLength, format, fName);
  990.         }
  991. }
  992.  
  993.  
  994.  
  995.  
  996.  
  997.  
  998.  
  999.  
  1000.  
  1001. void DMegaSequence::SearchORF( long& start, long& stop) 
  1002. {
  1003.     char  startc[2];
  1004.     long  i, j, k;
  1005.     short    ns;
  1006.     CodonStat  stops[10];
  1007.     
  1008.     start= kSearchNotFound;
  1009.     stop = kSearchNotFound;
  1010.     if (DCodons::NotAvailable()) return;
  1011.     
  1012.     for (ns= 0, i= 0; i<64; i++) {
  1013.         if (ns<10 && DCodons::amino(i) == '*') 
  1014.             stops[ns++] = DCodons::fCodons[i];
  1015.         }
  1016.     if (ns == 0) return;
  1017.         
  1018.     switch (fKind) {  
  1019.         case kRNA:
  1020.         case kDNA:
  1021.         case kNucleic: 
  1022.              start= Search( DCodons::startcodon(), FALSE);
  1023.              if (start == kSearchNotFound) return;
  1024.              for (j= start+3; j<fLength; j += 3) {
  1025.                  for (k=0; k<ns; k++) {
  1026.                      if (StrNICmp( fBases+j, stops[k].codon, 3) == 0) {
  1027.                          stop= j+3; // +3 to include this codon
  1028.                          return;
  1029.                          }
  1030.                      }
  1031.                  }
  1032.             break;
  1033.             
  1034.         case kAmino:
  1035.             startc[0]= DCodons::startamino();
  1036.             startc[1]= 0;
  1037.              start= Search( startc, FALSE);
  1038.              if (start == kSearchNotFound) return;
  1039.              for (j= start+1; j<fLength; j++) {
  1040.                  for (k=0; k<ns; k++) {
  1041.                      if (toupper(fBases[j]) == toupper(stops[k].amino)) {
  1042.                          stop= j+1; // +1 to include this codon
  1043.                          return;
  1044.                          }
  1045.                      }
  1046.                  }
  1047.             break;
  1048.             
  1049.         default:
  1050.             break;
  1051.         }
  1052. }
  1053.  
  1054.  
  1055.  
  1056. void DMegaSequence::NucleicSearch(char* source, char* target, SearchRec& aSearchRec)
  1057. {
  1058.     long k, j, tBits, lens, ti;
  1059.     Boolean done;
  1060.  
  1061.                     //find target[ti] where tBits == kMaskA,C,G,T for fastest search
  1062.                     //This part is wasted time for SearchAgain... store tBits/ti in saverec...
  1063.     lens= StrLen(target);
  1064.     for (j= 0, ti= 0, tBits= 0; j<lens && !tBits; j++) {
  1065.         ti= j;
  1066.         tBits= NucleicBits( target[ti]);
  1067.         tBits &= kMaskNucs; //    bClr( tBits, kBitExtra); //drop RNA bit
  1068.         }
  1069.  
  1070.     do {
  1071. reloop:
  1072.             aSearchRec.indx += aSearchRec.step; 
  1073.             aSearchRec.lim  -= aSearchRec.step;    
  1074.             
  1075.             if (aSearchRec.step>0) {
  1076.                 for (j= 0; j<aSearchRec.lim; j++)
  1077.                  // if (IsNucleicMatch( tBits, NucleicBits( source[j+aSearchRec.indx]))) 
  1078.                  if ( tBits & NucleicBits( source[j+aSearchRec.indx]) ) 
  1079.                  {
  1080.                     k= j; 
  1081.                     goto nextindx;
  1082.                  }
  1083.                 k= aSearchRec.lim;
  1084.                 }            
  1085.             else {  //step<0 IS BAD .. see UTextDoc version...
  1086.                 for (j= 0; j > -aSearchRec.lim; j--) 
  1087.                   //if (IsNucleicMatch( tBits, NucleicBits( source[j+aSearchRec.indx])))
  1088.                   if ( tBits & NucleicBits( source[j+aSearchRec.indx]) ) 
  1089.                 {
  1090.                     k= j; 
  1091.                     goto nextindx;
  1092.                     }
  1093.                 k= -aSearchRec.lim;
  1094.                 }
  1095.                 
  1096. nextindx:  
  1097.             aSearchRec.indx += k; 
  1098.             aSearchRec.lim  -= k;
  1099.                 //? not enough source left to match full target 
  1100.             if (aSearchRec.step>0) {
  1101.                 if (aSearchRec.lim < lens-ti) aSearchRec.lim= 0;
  1102.                 }            
  1103.             else {
  1104.                 if (aSearchRec.lim < ti) aSearchRec.lim= 0; //? or lim < ti-1 
  1105.                 }
  1106.             done= (aSearchRec.lim==0);
  1107.             
  1108.             if (!done) {
  1109.                 long srcstart= aSearchRec.indx - ti;
  1110.                 for (j= 0; j<lens; j++) 
  1111.                  if (j != ti) {
  1112.                     //if (!IsNucleicMatch( NucleicBits( target[j]), NucleicBits( source[j+srcstart]))) 
  1113.                   if (!(kMaskNucs & NucleicBits( target[j]) & NucleicBits( source[j+srcstart]))) 
  1114.                       goto reloop;
  1115.                     }
  1116.                 done= true;
  1117.                 }
  1118.         } while (!done);
  1119. }  
  1120.     
  1121.  
  1122. void DMegaSequence::ProteinSearch(char* source, char* target, SearchRec& aSearchRec)
  1123. {
  1124.     //just toupper match of chars 
  1125.     char      tChar; 
  1126.     Boolean  done;
  1127.     long        lens, k, j;
  1128.  
  1129.     lens= StrLen( target);
  1130.     tChar= toupper( target[0]);
  1131.     
  1132.     do {
  1133. reloop:
  1134.             aSearchRec.indx += aSearchRec.step; 
  1135.             aSearchRec.lim  -= aSearchRec.step;    
  1136.             
  1137.             if (aSearchRec.step>0) {
  1138.                 for (j= 0; j<aSearchRec.lim; j++) 
  1139.                  if (tChar == toupper( source[j+aSearchRec.indx])) {
  1140.                     k= j;
  1141.                     goto nextindx;
  1142.                     }
  1143.                 k= aSearchRec.lim;
  1144.                 }            
  1145.             else {
  1146.                 for (j= 0; j > -aSearchRec.lim; j--)
  1147.                  if (tChar == toupper(source[j+aSearchRec.indx])) {
  1148.                     k= j; 
  1149.                     goto nextindx;
  1150.                     }
  1151.                 k= -aSearchRec.lim;
  1152.                 }
  1153.                 
  1154. nextindx:  
  1155.             aSearchRec.indx += k; 
  1156.             aSearchRec.lim  -= k;
  1157.                 //? not enough source left to match full target 
  1158.             if (aSearchRec.step>0) {
  1159.                 if (aSearchRec.lim < lens-1) aSearchRec.lim= 0;
  1160.                 }            
  1161.             else {
  1162.                 if (aSearchRec.lim < 1) aSearchRec.lim= 0;  
  1163.                 }
  1164.             done= (aSearchRec.lim==0);
  1165.             
  1166.             if (!done) {
  1167.                 for (j= 1; j<lens; j++) {
  1168.                     if (toupper( target[j]) != toupper( source[j+aSearchRec.indx])) 
  1169.                         goto reloop;
  1170.                     }
  1171.                 done= true;
  1172.                 }
  1173.         } while (!done);
  1174. }  
  1175.  
  1176.  
  1177.     
  1178.  
  1179. long DMegaSequence::Search( char* target, Boolean backwards)
  1180. /* search for target in sequence;
  1181.     search == abs index into fBases[0..fLength] or kSearchNotFound
  1182.   if (target='') then find next  
  1183.   if (backwards) then backwards search
  1184. */
  1185. {
  1186.     long        limit, aStart;
  1187.     SearchRec  aSearchRec;
  1188.  
  1189.     aStart= fSelStart;
  1190.     if (!target || !*target) {  //search again
  1191.         if (fSearchRec.targ && (fSearchRec.step == -1 || fSearchRec.step == 1)) {  
  1192.             aSearchRec= fSearchRec;
  1193.             target= aSearchRec.targ;
  1194.             }        
  1195.         else {
  1196.             return kSearchNotFound;
  1197.             }
  1198.         }        
  1199.     else {
  1200.         limit= fLength; //StrLen(fBases);
  1201.         if (aStart < 0) aStart= 0;
  1202.         if (backwards) {
  1203.             if (!aStart) aStart= limit-1;
  1204.             else limit= aStart+1;  //? off-by-one ??
  1205.             }        
  1206.         else {
  1207.             if (aStart > limit) aStart= 0; 
  1208.             else limit -= aStart;
  1209.             }
  1210.         if (fSelBases > 0 && fSelBases < limit) limit= fSelBases;
  1211.         if (backwards) aSearchRec.step= -1;
  1212.         else aSearchRec.step= 1;
  1213.         aSearchRec.indx= aStart - aSearchRec.step;  //indx always in [0..handsize-1], except 1st is -1 
  1214.         aSearchRec.lim = limit + aSearchRec.step;  //lim always in [1..handsize] or 0=done, except 1st is hand+1 
  1215.         aSearchRec.targ= StrDup(target);
  1216.         }
  1217.  
  1218.     switch (fKind) {  
  1219.         case kRNA:
  1220.         case kDNA:
  1221.         case kNucleic: 
  1222.             NucleicSearch(fBases,target,aSearchRec); 
  1223.             break;
  1224.         default:
  1225.             ProteinSearch(fBases,target,aSearchRec);
  1226.             break;
  1227.         }
  1228.     
  1229.     fSearchRec= aSearchRec;
  1230.     if (aSearchRec.lim == 0) return kSearchNotFound;
  1231.     else return aSearchRec.indx;
  1232. }  
  1233.  
  1234.  
  1235.